#hide
import fastbook
fastbook.setup_book()


#hide
from fastbook import *
from fastai.vision.widgets import *


import os
key = os.environ.get('AZURE_SEARCH_KEY', 'XXX')


search_images_bing


results = search_images_ddg('grizzly bear')
results


#hide
ims = ['http://3.bp.blogspot.com/-S1scRCkI3vY/UHzV2kucsPI/AAAAAAAAA-k/YQ5UzHEm9Ss/s1600/Grizzly%2BBear%2BWildlife.jpg']


dest = 'images/grizzly.jpg'
download_url(ims[0], dest)


im = Image.open(dest)
im.to_thumb(128,128)


bear_types = 'grizzly','black','teddy'
path = Path('bears')


if not path.exists():
    path.mkdir()
for o in bear_types:
    print("start download img ",o)
    dest = (path/o)
    dest.mkdir(exist_ok=True)
    results = search_images_ddg(f'{o} bear',20)
    download_images(dest, urls=results)


fns = get_image_files(path)
fns


failed = verify_images(fns)
failed


failed.map(Path.unlink);


bears = DataBlock(
    blocks=(ImageBlock, CategoryBlock), 
    get_items=get_image_files, 
    splitter=RandomSplitter(valid_pct=0.2, seed=12),
    get_y=parent_label,
    item_tfms=Resize(128))


# bs 一次交付给gpu的样本数
dls = bears.dataloaders(path,bs=64)


dls.valid.show_batch(max_n=64, nrows=3) # 确认集显示


# 拉伸
bears = bears.new(item_tfms=Resize(128, ResizeMethod.Squish)) 
dls = bears.dataloaders(path)
dls.valid.show_batch(max_n=64, nrows=3)


# 填充 黑色
bears = bears.new(item_tfms=Resize(128, ResizeMethod.Pad, pad_mode='zeros'))
dls = bears.dataloaders(path)
dls.valid.show_batch(max_n=64, nrows=3)


# 对原有图像进行缩放，缩放比为min_scale
bears = bears.new(item_tfms=RandomResizedCrop(128, min_scale=0.3))
dls = bears.dataloaders(path,bs=5)
dls.train.show_batch(max_n=64, nrows=2, unique=True)


bears = bears.new(item_tfms=Resize(128), batch_tfms=aug_transforms(mult=2))
dls = bears.dataloaders(path,bs=10)
dls.train.show_batch(max_n=10, nrows=2, unique=True)


bears = bears.new(
    item_tfms=RandomResizedCrop(224, min_scale=0.5),
    batch_tfms=aug_transforms())
dls = bears.dataloaders(path,bs=20)


learn = vision_learner(dls, resnet18, metrics=error_rate)
learn.fine_tune(4)


# 分类说明器 - 从我们训练的模型中创建混淆矩阵
interp = ClassificationInterpretation.from_learner(learn)
interp.plot_confusion_matrix()


interp.plot_top_losses(5, nrows=3)


#hide_output
cleaner = ImageClassifierCleaner(learn)
cleaner


#hide
# 遍历清理器中被标记为删除的数组 - 将其从数据中删除
for idx in cleaner.delete(): 
    cleaner.fns[idx].unlink()
# 变量清理器中标签被改变的数组，将其移动到新文件夹
for idx,cat in cleaner.change(): 
    shutil.move(str(cleaner.fns[idx]), path/cat)


learn.export()


path = Path()
path.ls(file_exts='.pkl')


learn_inf = load_learner(path/'export.pkl')


learn_inf.predict('images/grizzly.jpg')


learn_inf.dls.vocab


#hide_output
btn_upload = widgets.FileUpload()
btn_upload


#hide
# 对于这本书，我们不能真正点击上传按钮，所以我们伪造了它
btn_upload = SimpleNamespace(data = ['images/grizzly.jpg'])


img = PILImage.create(btn_upload.data[-1])
img.to_thumb(128,128)


#hide_output
out_pl = widgets.Output()
out_pl.clear_output()
with out_pl: display(img.to_thumb(128,128))
out_pl


pred,pred_idx,probs = learn_inf.predict(img)


#hide_output
lbl_pred = widgets.Label()
lbl_pred.value = f'预测: {pred}; 概率: {probs[pred_idx]:.04f}'
lbl_pred


#hide_output
btn_run = widgets.Button(description='分类')
btn_run


def on_click_classify(change):
    img = PILImage.create(btn_upload.data[-1])
    out_pl.clear_output()
    with out_pl: display(img.to_thumb(128,128))
    pred,pred_idx,probs = learn_inf.predict(img)
    lbl_pred.value = f'预测: {pred}; 概率: {probs[pred_idx]:.04f}'

btn_run.on_click(on_click_classify)


#hide
# 将btn_upload放回下一个单元格的小部件
btn_upload = widgets.FileUpload()


#hide_output
VBox([widgets.Label('选择你的熊!'), 
      btn_upload, btn_run, out_pl, lbl_pred])


#hide
# !pip install voila
# !jupyter serverextension enable --sys-prefix voila 


#hide
get_ipython().getoutput("pip install voila")


#hide
get_ipython().getoutput("jupyter serverextension enable --sys-prefix voila ")



